/**
 * Created by JetBrains WebStorm.
 * User: denysk
 * Date: 6/11/11
 * Time: 11:20 PM
 * To change this template use File | Settings | File Templates.
 */
Namespace("sketch.ui");

(function(fwk, ui, $){
    ui.PropertyDesigner = klass(null, {
        _constructor: function(domSelector, commands){
            this.domSelector = domSelector;
            this.commands = commands;
            this.bindings = [];
            this.destructors = [];
        },

        clear: function(){
            each(this.destructors, function(d){
                d();
            });

            $(this.domSelector).empty();

            for (var i = 0, len = this.bindings.length; i < len; ++i) {
                var binding = this.bindings[i];
                binding.property.unbind(binding.binding);
            }

            this.bindings = [];
            this.destructors = [];
        },

        update: function(uiElement){
            this.clear();

            this._updateProperties($(this.domSelector), uiElement.properties);
        },

        _updateProperties: function(element, propertyBag, namePrefix) {
            var properties = propertyBag.getEditableProperties();

            for (var i = 0, l = properties.length; i < l; ++i) {
                var property = properties[i];
                var uniqueName = namePrefix ? namePrefix + "_" + property.propertyName : property.propertyName;

                if (property.defaultValue instanceof fwk.Properties) {
                    this._updateProperties(element, propertyBag.get(property.propertyName), uniqueName);
                }
                else {
                    this._updatePropertyEditor(element, property, uniqueName);
                }
            }
        },

        _updatePropertyEditor: function(element, property, uniqueName){
            var elementId = "property_" + uniqueName;
            var container = element.append("<div id='"+ elementId + "'></div>");
            var editor = $(property.editorTemplateSelector);
            var that = this;

            var mediator = {
                commandManager: fwk.commandManager,
                setValue: function(value){
                    if (this.originalPropertyValue === undefined){
                        this.originalPropertyValue = property();
                    }
                    property(value);
                },
                setValueByCommand: function(value){
                    var command = new that.commands.PropertyChanged(property);
                    if (this.originalPropertyValue !== undefined){
                        command.oldValue = this.originalPropertyValue;
                    }
                    command.value = value;
                    fwk.commandManager.execute(command);
                    this.originalPropertyValue = undefined;
                },
                getArgument: function(){
                    return property.editorTemplateArgument;
                },
                validateNewValue: function(value){
                    return property.validateNewValue(value);
                }
            };

            $("#" + elementId).data("mediator", mediator);

            editor.tmpl({
                        name: property.propertyName,
                        uniqueName: uniqueName,
                        description: property.description,
                        value: property(),
                        controlId: uniqueName + "_input",
                        mediatorHolder: elementId,
                        possibleValues: JSON.stringify(property.possibleValues())})
                    .appendTo("#" + elementId);

            var initFunction = editor.data("init");
            if (!initFunction) {
                throw {name: "InvalidOperationException", message: "The editor must have an init function in its dictionary"};
            }
            initFunction();

            var setValueFunction = editor.data("setValue");
            if (setValueFunction){
                property.bind(setValueFunction);
                this.bindings.push({property: property, binding: setValueFunction});
            }

            var disposeFunction = editor.data("dispose");
            if (disposeFunction){
                this.destructors.push(disposeFunction);
            }
        }
    });
})(sketch.framework, sketch.ui, jQuery);